<?php
namespace api\modules\v1\models\redPacket;

use api\modules\v1\models\Common;
use api\modules\v1\models\friend\Friend;
use api\modules\v1\models\group\Group;
use api\modules\v1\models\group\GroupUser;
use api\modules\v1\models\user\User;
use api\modules\v1\models\user\UserLoginErrorLog;
use common\models\CacheKeys;
use common\models\Functions;
use common\models\im\Im;
use common\models\redPacket\RedPacketLog;
use common\models\Status;
use common\models\user\UserUnusualLog;
use common\models\userFund\UserMoneyLog;
use linslin\yii2\curl\Curl;
use Yii;
use yii\base\Exception;

/**
 * This is the model class for table "goods".
 *
 * @property int $id
 * @property string $name
 */
class RedPacket extends \common\models\redPacket\RedPacket
{
    public $COMBINATIONS = [[0,1,2],[0,1,3],[0,1,4],[0,1,5],[0,1,6],[0,1,7],[0,1,8],[0,1,9],[0,2,3],[0,2,4],[0,2,5],[0,2,6],[0,2,7],[0,2,8],[0,2,9],[0,3,4],[0,3,5],[0,3,6],[0,3,7],[0,3,8],[0,3,9],[0,4,5],[0,4,6],[0,4,7],[0,4,8],[0,4,9],[0,5,6],[0,5,7],[0,5,8],[0,5,9],[0,6,7],[0,6,8],[0,6,9],[0,7,8],[0,7,9],[0,8,9],[1,2,3],[1,2,4],[1,2,5],[1,2,6],[1,2,7],[1,2,8],[1,2,9],[1,3,4],[1,3,5],[1,3,6],[1,3,7],[1,3,8],[1,3,9],[1,4,5],[1,4,6],[1,4,7],[1,4,8],[1,4,9],[1,5,6],[1,5,7],[1,5,8],[1,5,9],[1,6,7],[1,6,8],[1,6,9],[1,7,8],[1,7,9],[1,8,9],[2,3,4],[2,3,5],[2,3,6],[2,3,7],[2,3,8],[2,3,9],[2,4,5],[2,4,6],[2,4,7],[2,4,8],[2,4,9],[2,5,6],[2,5,7],[2,5,8],[2,5,9],[2,6,7],[2,6,8],[2,6,9],[2,7,8],[2,7,9],[2,8,9],[3,4,5],[3,4,6],[3,4,7],[3,4,8],[3,4,9],[3,5,6],[3,5,7],[3,5,8],[3,5,9],[3,6,7],[3,6,8],[3,6,9],[3,7,8],[3,7,9],[3,8,9],[4,5,6],[4,5,7],[4,5,8],[4,5,9],[4,6,7],[4,6,8],[4,6,9],[4,7,8],[4,7,9],[4,8,9],[5,6,7],[5,6,8],[5,6,9],[5,7,8],[5,7,9],[5,8,9],[6,7,8],[6,7,9],[6,8,9],[7,8,9]];

    /**
     * 发送红包
     * @return array
     */
    public function send() {
        $redis = Yii::$app->redis;

        $user = Yii::$app->getUser()->getIdentity()->toArray();
        $trans = static::getDb()->beginTransaction();
        $key = "SEND_RED_PACKET_".$user['id'];
        $post = Yii::$app->request->post();

        try {
            $userId = $user['id'];
            if (!$userId) {
                throw new Exception('未知用户，不能发红包！');
            }
            // 检查用户是否可以发送红包
            (new \common\models\user\User()) -> checkRedPacketInfo($user);

            # 零钱封禁
            UserUnusualLog::checkUserUnusual($user['id'],Status::USER_UNUSUAL_TYPE_MONEY);

            // 检查设备码
            Common::checkDeviceCode($user);

            // 检查用户信息
            (new \common\models\user\User()) -> checkInfo($user);


            $payPassword = Yii::$app->request->post('pay_password','');
            $name = Yii::$app->request->post('name','');
            $type = Yii::$app->request->post('type',0);
            $txCode = Yii::$app->request->post('tx_code','');  // 群或者用户tx_code
            $money = Yii::$app->request->post('money',0);
            $num = Yii::$app->request->post('num',0);
            $groupUserTxCode = Yii::$app->request->post('group_user_tx_code',0); // 群成员tx_code

            $receiveUserId = 0;//接收ID 群id  用户id
            $receiveGroupId = 0;//接收ID 群id  用户id
//            # 检查支付密码密码
//            UserLoginErrorLog::chkPayPassword($user['login_name']);

            if (empty($payPassword)) {
                throw new Exception('交易密码不能为空！');
            }

            if ((!Yii::$app->security->validatePassword($payPassword, $user['pay_password']))) {
                throw new Exception("交易密码不正确",2001);
            }

            $config = static::getCommonByKey(['switch_group_red_packet','switch_user_red_packet','switch_exclusive_red_packet','max_red_packet_money','group_daily_max_num']);

            if ($type == Status::RED_PACKET_TYPE_GROUP) {
                if ($config['switch_group_red_packet'] == Status::COMMON_RADIO_NO) {
                    throw new Exception('系统维护，暂停发包！');
                }

                if($money > $config['max_red_packet_money']) {
                    throw new Exception('单个金额超限！');
                }

                $params = Yii::$app->request->post();
                return $this->sendOpen($params,$user['id']);
            }

//            CacheKeys::checkFrequency($userId,1);
//            CacheKeys::checkFrequency($key,1);

            if ($type == Status::RED_PACKET_TYPE_USER || $type == Status::RED_PACKET_TYPE_EXCLUSIVE) {
                $num = 1;
            }

            if (!is_numeric($money) || !is_numeric($num) || !is_numeric($type)) {
                throw new Exception('发包异常');
            }

            // if ((!Yii::$app->security->validatePassword($payPassword, $user['pay_password']))) {
            //     throw new Exception("交易密码不正确");
            // }

            if (!$num) {
                throw new Exception('红包数量不能为零！');
            }

            if ($num > 80) {
                throw new Exception('红包数量超过最大数量！');
            }

            if(!$type) {
                throw new Exception('红包类型不能为空！');
            }

            if(!in_array($type, array_keys(Status::RED_PACKET_TYPE_MAP))) {
                throw new Exception('红包类型不合法！');
            }

            if(!$money) {
                throw new Exception('红包金额不能为零！');
            }

            if(!$txCode) {
                throw new Exception('接收方账号不能为空！');
            }

            if($money < 0.01) {
                throw new Exception('红包金额太少！');
            }

            if($user['money'] < $money) {
                throw new Exception('金额不足，无法发红包！');
            }

            if($money > $config['max_red_packet_money']) {
                throw new Exception('单个金额超限！');
            }

            $exists = $redis->get(CacheKeys::IM_SEND_RED_PACKET . $userId);
            if($exists){
                throw new Exception('您的速度太快了！');
            }
            $redis->set(CacheKeys::IM_SEND_RED_PACKET . $userId, true);

            $amount = $money;
            $singleMin = 0.01;
            $singleMax = $money;
//            if ($amount > $singleMin || $amount < $singleMax ) {
//                throw new Exception("金额不能大于{$singleMax}不能小于{$singleMin}");
//            }

            if ($num * $singleMin > $amount) {
                throw new Exception("金额不足够发{$num}个红包！");
            }



            //判断个人红包还是群红包
            if ($type == Status::RED_PACKET_TYPE_USER) {
                // 个人红包
                if ($config['switch_user_red_packet'] == Status::COMMON_RADIO_NO) {
                    throw new Exception('系统维护，暂停发包！');
                }
                $receiveUser = User::getOneByWhere(['tx_code' => $txCode]);

                if (empty($receiveUser)) {
                    throw new Exception("未知接收用户！");
                }

                $userFriendInfo = Friend::getOneByWhere([
                    'user_id' => $userId,
                    'friend_id' => $receiveUser['id'],
                ]);

                if (empty($userFriendInfo)) {
                    throw new Exception("你和他不是好友，无法发送红包！");
                }

                $receiveUserId = $receiveUser['id'];


            } else {
                // 群红包
                //群信息

                $groupInfo = Group::getOneByWhere(['tx_code' => $txCode]);
                if (empty($groupInfo)) {
                    throw new Exception("该群不存在！");
                }

                if ($groupInfo['status'] == Status::COMMON_RADIO_NO) {
                    throw new Exception('群已被封禁，无法发送红包！');
                }

                $groupUserInfo = GroupUser::getOneByWhere(['user_id' => $userId,'group_id' => $groupInfo['id']]);
                if (empty($groupUserInfo)) {
                    throw new Exception("你不是该群成员，无法发送红包！");
                }

                // 一天之内发送超过1000个红包就封停群聊
                if ($config['group_daily_max_num'] > 0) {
                    $countWhere['group_id'] = $groupInfo['id'];
                    $countWhere['type'] = Status::RED_PACKET_TYPE_GROUP;
                    $countAndWhere[] = ["between", 'create_time', date("Y-m-d 00:00:00"), date("Y-m-d 23:59:59")];
                    $countRed = static::getCountByAndWhere($countWhere,$countAndWhere);
                    if($countRed >= $config['group_daily_max_num']){
                        throw new Exception("红包发送数量太多，今日暂停发送！");
                    }
                }

                if ($type == Status::RED_PACKET_TYPE_EXCLUSIVE) {
                    // 专属红包
                    if ($config['switch_exclusive_red_packet'] == Status::COMMON_RADIO_NO) {
                        throw new Exception('系统维护，暂停发包！');
                    }
                    $toGroupUserInfo = GroupUser::getOneByWhere(['user_tx_code' => $groupUserTxCode,'group_id' => $groupInfo['id']]);
                    if (empty($toGroupUserInfo)) {
                        throw new Exception("该用户不是该群成员，无法发送红包！");
                    }
                    $receiveUserId = $toGroupUserInfo['user_id'];
                }

                if ($config['switch_group_red_packet'] == Status::COMMON_RADIO_NO) {
                    throw new Exception('系统维护，暂停发包！');
                }

                $receiveGroupId = $groupUserInfo['group_id'];

            }


            // 3.开始执行发红包
            $redPacket = $this->createRedPacket($user,$money,$type,$receiveUserId,$num, $name, $receiveGroupId);
            if (empty($redPacket)) {
                throw new Exception("红包发送失败");
            }
            $imModel = new Im();
            // 4.发送消息
            // 4.1发送群消息
            if ($type == Status::RED_PACKET_TYPE_GROUP && isset($groupInfo) && !empty($groupInfo)) {
                // 发送im消息
                $publicGroupMessage['message_type'] = (int) Status::MESSAGE_TYPE_GROUP_USER_SEND_RED_PACKET;
                $publicGroupMessage['red_packet_id'] = (int) $redPacket['id'];
                $publicGroupMessage['red_packet_type'] = (int) $redPacket['type'];
                $publicGroupMessage['name'] = $redPacket['name'];
                $publicGroupMessage['user_face'] = $user['user_face'] ? static::getAvatar($user['user_face']) : '';
                $publicGroupMessage['nick_name'] = $user['nick_name'] ?: '';
                $publicGroupMessage['tx_code'] = $redPacket['user_tx_code'];
                $publicGroupMessage['type'] = (int) Status::MESSAGE_TYPE_GROUP_USER_SEND_RED_PACKET;
                $publicGroupMessage['receive_id'] = (int) $redPacket['to_id'];
                $publicGroupMessage['receive_tx_code'] = $groupInfo['tx_code'];
                $publicGroupMessage['money'] = $redPacket['money'];
                $publicGroupMessage['time'] = date('Y-m-d H:i:s');
                $imRes = $imModel->sendGroupMessage($groupInfo['tx_code'], $publicGroupMessage, $redPacket['user_tx_code']);
                if (!$imRes) {
                    throw new Exception("发红包异常");
                }
            }
            // 4.2 发送专属消息
            if ($type == Status::RED_PACKET_TYPE_EXCLUSIVE && isset($groupInfo) && !empty($groupInfo) && isset($toGroupUserInfo) && !empty($toGroupUserInfo)) {
                // 发送im消息
                $publicGroupMessage['message_type'] = (int) Status::MESSAGE_TYPE_GROUP_USER_SEND_RED_PACKET;
                $publicGroupMessage['red_packet_id'] = (int) $redPacket['id'];
                $publicGroupMessage['red_packet_type'] = (int) $redPacket['type'];
                $publicGroupMessage['name'] = $redPacket['name'];
                $publicGroupMessage['user_face'] = $user['user_face'] ? static::getAvatar($user['user_face']) : '';
                $publicGroupMessage['nick_name'] = $user['nick_name'] ?: '';
                $publicGroupMessage['tx_code'] = $redPacket['user_tx_code'];
                $publicGroupMessage['type'] = (int) Status::MESSAGE_TYPE_GROUP_USER_SEND_RED_PACKET;
                $publicGroupMessage['receive_id'] = (int) $redPacket['to_id'];
                $publicGroupMessage['receive_tx_code'] = $toGroupUserInfo['user_tx_code'];
                $publicGroupMessage['receive_nick_name'] = $toGroupUserInfo['business_card'] ? $toGroupUserInfo['business_card'] : $toGroupUserInfo['user_nick_name'];
                $publicGroupMessage['show_exclusive_red_packet'] = (int) $groupInfo['show_exclusive_red_packet'];
                $publicGroupMessage['money'] = $redPacket['money'];
                $publicGroupMessage['time'] = date('Y-m-d H:i:s');
                $imRes = $imModel->sendGroupMessage($groupInfo['tx_code'], $publicGroupMessage, $redPacket['user_tx_code']);
                if (!$imRes) {
                    throw new Exception("发红包异常");
                }
            }

            // 4.3 发送个人消息
            if ($type == Status::RED_PACKET_TYPE_USER && isset($userFriendInfo) && !empty($userFriendInfo)) {
                $userMessage['message_type'] = (int) Status::MESSAGE_TYPE_GROUP_USER_SEND_RED_PACKET;
                $userMessage['red_packet_id'] = (int) $redPacket['id'];
                $userMessage['red_packet_type'] = (int) $redPacket['type'];
                $userMessage['name'] = $redPacket['name'];
                $userMessage['user_face'] = $user['user_face'] ? static::getAvatar($user['user_face']) : '';
                $userMessage['nick_name'] = $user['nick_name'] ?: '';
                $userMessage['tx_code'] = $redPacket['user_tx_code'];
                $userMessage['type'] = (int) Status::MESSAGE_TYPE_GROUP_USER_SEND_RED_PACKET;
                $userMessage['receive_id'] = $redPacket['to_id'];
                $userMessage['receive_tx_code'] = $userFriendInfo['friend_tx_code'];
                $userMessage['money'] = $redPacket['money'];
                $userMessage['time'] = date('Y-m-d H:i:s');

                $imRes = $imModel->sendUserMessage($userFriendInfo['friend_tx_code'], $userMessage, $redPacket['user_tx_code']);
                if (!$imRes) {
                    throw new Exception("发红包异常");
                }
            }


            $trans->commit();
            return Functions::formatRestAPI(0, '发送成功', $redPacket);
        }  catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '服务异常');
        } catch (Exception $e) {
            $trans->rollBack();
            if ($e->getCode() == 2001) {
                UserLoginErrorLog::recordLog($user['login_name'], $post['pay_password'], '支付密码错误', 2);
            }
            return Functions::formatRestAPI($e->getCode() ? $e->getCode() : 1, $e->getMessage());
        } finally {
            $redis->del(CacheKeys::IM_SEND_RED_PACKET . $userId);
        }
    }


    // 创建红包
    public function createRedPacket(
        $userInfo = [],
        $money = 0,
        $type = Status::RED_PACKET_TYPE_USER,
        $receiveUserId = 0,
        $num,
        $name,
        $receiveGroupId = 0
    ) {
        $redis = Yii::$app->redis;
        if (!$userInfo || !$money || !$type || !$num) {
            return null;
        }

        if ($type == Status::RED_PACKET_TYPE_USER) {
            if (!$receiveUserId) {
                return null;
            }
        } else {
            if (!$receiveGroupId) {
                return null;
            }
            if ($type == Status::RED_PACKET_TYPE_EXCLUSIVE) {
                if (!$receiveUserId) {
                    return null;
                }
            }
        }

        // 加入红包表
        $insertRedPacket['name'] = (string) $name;
        $insertRedPacket['user_id'] = (int) $userInfo['id'];
        $insertRedPacket['num'] = (int) $num;
        $insertRedPacket['user_code'] = $userInfo['user_code'];
        $insertRedPacket['user_phone'] = $userInfo['login_name'];
        $insertRedPacket['user_tx_code'] = $userInfo['tx_code'];
        $insertRedPacket['user_face'] = $userInfo['user_face'];
        $insertRedPacket['user_nick_name'] = $userInfo['nick_name'];
        $insertRedPacket['money'] = $money;
        $insertRedPacket['receive_num'] = 0;         // 领取数量
        $insertRedPacket['type'] = (int) $type;      // 1-个人 2-群 3-群专属
        $insertRedPacket['to_id'] = (int) $type == Status::RED_PACKET_TYPE_GROUP ? $receiveGroupId : $receiveUserId;// 个人id 或者群id
        $insertRedPacket['create_time'] = date('Y-m-d H:i:s');
        $insertRedPacket['finish_time'] = '';
        $insertRedPacket['status'] = Status::RED_PACKET_WAIT;
        $insertRedPacket['group_id'] = $type == Status::RED_PACKET_TYPE_USER ? 0 : $receiveGroupId; //群id

        $resRedPacketInsert = static::insertData($insertRedPacket);
        if ($resRedPacketInsert === false) {
            throw new Exception('系统异常，请稍后尝试！');
        }

        $insertRedPacket['id'] = (int) $resRedPacketInsert;

        // 拼接返回信息
        unset($insertRedPacket['user_phone']);
        unset($insertRedPacket['user_code']);
        unset($insertRedPacket['user_face']);
        unset($insertRedPacket['user_nick_name']);
        $return = $insertRedPacket;

        //红包信息放入缓存
        $redis->set(CacheKeys::IM_RED_PACKET.$resRedPacketInsert, json_encode($return));
        $redis->expire(CacheKeys::IM_RED_PACKET.$resRedPacketInsert, 24*60*60);


        // 余额信息
        UserMoneyLog::record(
            $userInfo['id'],
            Status::PROP_TYPE_MONEY,
            Status::MONEY_LOG_TYPE_SEND_RED_PACKET,
            -1 * $money,
            Status::MONEY_LOG_TYPE_MAP[Status::MONEY_LOG_TYPE_SEND_RED_PACKET] ?? '',
            '发送红包',
            $resRedPacketInsert
        );


        $moneyList = $this->buildRandomResults(
            $money,
            $num,
            0.65,
            1,
            10000,
            false,
            3
        );

//        $moneyList = $this->buildRandomResults(
//            $money,
//            $num,
//            0.1,
//            4,
//            10000,
//            false,
//            3
//        );

        // 新版发红包
        $average = static::getCommonByKey('red_packet_average');
        if ($average != 6) {
            $moneyList = $this->generateRedPacket(
                $money,
                $num,
                $average
            );
        } else {
            $moneyList = $this->buildRandomResults(
                $money,
                $num,
                0.65,
                1,
                10000,
                false,
                3
            );
        }


        if ($moneyList) {
            rsort($moneyList);
            $maxMoney = $moneyList[0];

            shuffle($moneyList);
            $redPacketLogModel = new RedPacketLog();

            $logRedisData = [];
            foreach ($moneyList as $value) {
                $logData = $redisLog = [];
                $redisLog['red_packet_id'] = $logData['red_packet_id'] = (int) $resRedPacketInsert;
                $redisLog['user_id'] = $logData['user_id'] = $userInfo['id'];
                $redisLog['user_code'] = $logData['user_code'] = $userInfo['user_code'];
                $logData['user_phone'] = $userInfo['login_name'];
                $redisLog['user_tx_code'] = $logData['user_tx_code'] = $userInfo['tx_code'];
                $redisLog['name'] = $logData['name'] = $name;
                $redisLog['money'] = $logData['money'] = $money;
                $redisLog['num'] = $logData['num'] = $num;
                $redisLog['status'] = $logData['status'] = Status::RED_PACKET_WAIT;  //1-待领取 2-已领取 3-已退回
                $redisLog['type'] = $logData['type'] = $type;   //1-个人红包 2-群红包 3-专属红包
                $redisLog['to_id'] = $logData['to_id'] =  (int) $type == Status::RED_PACKET_TYPE_GROUP ? $receiveGroupId : $receiveUserId;  // 可以接收的用户或者群ID
                $redisLog['group_id'] = $logData['group_id'] = $type == Status::RED_PACKET_TYPE_USER ? 0 : $receiveGroupId;
                $redisLog['create_time'] = $logData['create_time'] = date('Y-m-d H:i:s');
                $redisLog['receive_money'] = $logData['receive_money'] = $value;
                $redisLog['is_max'] = $logData['is_max'] = $maxMoney == $value ? Status::COMMON_RADIO_YES: Status::COMMON_RADIO_NO;
                $resLog = $redPacketLogModel::insertData($logData);
                if ($resLog === false) {
                    throw new Exception('系统异常，请稍后尝试');
                }
                $redisLog['id'] = $logData['id'] = $resLog;


                $logRedisData[] = $logData;

                $redis->lpush(CacheKeys::IM_RED_PACKET_WAIT_LIST.$resRedPacketInsert, json_encode($redisLog));
            }

            //红包信息放入缓存
//            $redis->set(CacheKeys::IM_RED_PACKET_LIST.$resRedPacketInsert,json_encode($logRedisData));
//            $redis->expire(CacheKeys::IM_RED_PACKET_LIST.$resRedPacketInsert, 24*60*60);
            $redis->expire(CacheKeys::IM_RED_PACKET_WAIT_LIST.$resRedPacketInsert, 24*60*60);

        } else {
            throw new Exception('红包发送失败');
        }

        return $return;

    }

    /**
     * @param float $amount 总红包金额
     * @param int $quantity 总数量
     * @param float $minRate 拨总金额的多少作为低保 数字越低 个人得到的金额差额越大
     * @param int $prizeMultiple 奖励浮动 数字越高 个人得到金额差额越大
     * @param int $precision 奖励偏移精度 10000
     * @param bool $allowBalanceLastNum 允许平衡分位分布
     * @param int $maxTimes 最多允许出现次数
     * @return array
     */
    private function buildRandomResults(
        $amount,
        $quantity,
        $minRate = 0.5,
        $prizeMultiple = 4,
        $precision = 10000,
        $allowBalanceLastNum = false,
        $maxTimes = 3
    ) {

        // 仅够低保
        if ($amount / $quantity <= 0.01) {
            $ret = [];
            for ($i = 0; $i < $quantity; $i++) {
                $ret[] = 0.01;
            }
            return $ret;
        }

        $minAmount = $this->formatMoney($amount * $minRate);

        $minMinAmount = $quantity * 0.01;
        if ($minAmount < $minMinAmount) {
            $minAmount = $minMinAmount;
        }
        $minAverage = $this->formatMoney($minAmount / $quantity);

        $ret = [];
        $last = $amount - $minAmount;
        $maxRand = $prizeMultiple * $precision;

        for ($i = 0; $i < $quantity; $i++) {
            $rate = mt_rand(0, $maxRand) / $precision;
            $changeAmount = $this->formatMoney($last / ($quantity - $i) * $rate);
            $changeAmount = $changeAmount > $last ? $last : $changeAmount;
            $thisAmount = $this->formatMoney($minAverage + $changeAmount);
            $thisAmount = number_format($thisAmount, 2);


            $ret[] = $thisAmount;
            $last -= $changeAmount;
        }
        $last = round($last, 2);
        $retCount = count($ret);
        if ($last > 0) {
            $index = $retCount - 1;
            $ret[$index] = $this->formatMoney($ret[$index] + $last);
        }

        if ($allowBalanceLastNum && ($amount / $quantity >= 1)) {
            $this->balanceLastNum($ret, $maxTimes);
        }
        $this->fixedResults($ret, $amount);

        // 出现负数问题
        $isHaveFushu = false;
        foreach ($ret as $value) {
            if ($value <= 0) {
                $isHaveFushu = true;
            }
        }

        if ($isHaveFushu) {
            $ret = $this->buildRandomResults(
                $amount,
                $quantity,
                $minRate,
                $prizeMultiple,
                $precision,
                $allowBalanceLastNum,
                $maxTimes
            );
        }

        return $ret;
    }


    public function getRandMoney ($maxRand = 0,$precision = 0, $index = 0, $quantity = 0, $last = 0, $minAverage = 0) {
        $rate = mt_rand(0, $maxRand) / $precision;
        $changeAmount = $this->formatMoney($last / ($quantity - $index) * $rate);
        $changeAmount = $changeAmount > $last ? $last : $changeAmount;
        $thisAmount = $this->formatMoney($minAverage + $changeAmount);
        return [$changeAmount,number_format($thisAmount, 2)];
    }

    /**
     * 重平衡分位 让分位重复次数限制在一定范围内
     *
     * @param array $ret
     * @param int $maxTimes
     */
    private function balanceLastNum(&$ret, $maxTimes) {
        // init data
        $lastNums = [];

        // start random
        $retCount = count($ret);
        $randomTimes = ceil($retCount / $this->COMBINATION_SIZE);
        $combinationMaxIndex = count($this->COMBINATIONS) - 1;
        for ($i = 0; $i < $randomTimes; $i++) {
            $arr = $this->COMBINATIONS[mt_rand(0, $combinationMaxIndex)];
            foreach ($arr as $num) {
                $lastNums[] = $num;
            }
        }

        $index = 0;
        $disTotal = 0;
        foreach ($ret as $num) {
            $originalNum = floor($ret[$index] * 100);
            $lastNum = $originalNum % 10;
            $newNum = $originalNum - $lastNum + $lastNums[$index];
            $ret[$index] = $newNum / 100;
            $disTotal = $originalNum - $newNum;
            $index++;
        }
        $ret[$index - 1] += $disTotal / 100;
    }

    private function fixedResults(&$results, $amount)
    {
        $total = 0;
        foreach ($results as $r) {
            $total = bcadd($total,$r,2);
//            $total += $r;
        }
        $dis = round($amount - $total, 2);
        if ($dis >= 0.01 || $dis <= 0.01) {
//        if ($dis >= 0.01) {
            $results[count($results) - 1] = (string) bcadd($results[count($results) - 1], $dis, 2);
        }
    }

    private function formatMoney($money)
    {
        return floatval(number_format($money, 2, '.', ''));
    }



    /**
     * 红包状态
     * @param Integer $id
     * @return array
     * state 6  -  红包已过期 自己领取了或者是自己的红包
     * state 5  -  个人红包 或者专属 但是当前用户不能领取
     * state 4  -  红包已过期 自己未领取或者不是自己的红包
     * state 3  -  已被领取完
     * state 2  -  已领取
     * state 1  -  未领取
     * 可以直接跳转到详情的 2 3 6
     */
    public function state($id = 0)
    {
        $redis = Yii::$app->redis;
        $user = Yii::$app->getUser()->getIdentity()->toArray();

        try {
            if (empty($id)) {
                throw new Exception('参数错误');
            }
            $redPacketInfo = $redis->get(CacheKeys::IM_RED_PACKET.$id);
            $redPacketInfo = json_decode($redPacketInfo,true);
            if (empty($redPacketInfo)) {

                // 是否领取了
                $where = $andWhere = [];
                $andWhere[] = [
                    'or',
                    ['=','user_id',$user['id']],
                    ['=','receive_user_id',$user['id']],
                ];
                $where['status'] = Status::RED_PACKET_DONE;
                $isView = \api\modules\v1\models\redPacket\RedPacketLog::getOneByAndWhere($where,$andWhere,'id');
                if ($isView) {
                    $data['state'] = 6;   // 红包已过期 自己领取了或者是自己的红包
                    return Functions::formatRestAPI(0, '', $data);
                }
                $data['state'] = 4;   // 红包已过期 自己未领取或者不是自己的红包
                return Functions::formatRestAPI(0, '', $data);
            }

            // 个人红包
            if ($redPacketInfo['type'] == Status::RED_PACKET_TYPE_USER && $redPacketInfo['status'] == Status::RED_PACKET_WAIT) {
                if ($redPacketInfo['to_id'] != $user['id']){
                    $data['state'] = 5;
                    return Functions::formatRestAPI(0, '', $data);
                }
            }

            // 群红包 专属红包
            if ($redPacketInfo['type'] == Status::RED_PACKET_TYPE_GROUP || $redPacketInfo['type'] == Status::RED_PACKET_TYPE_EXCLUSIVE) {
                $groupUserInfo = GroupUser::getOneByWhere(['group_id' => $redPacketInfo['group_id'],'user_id' => $user['id']]);
                if (!$groupUserInfo) {
                    throw new Exception('你不是该群成员，无法领取红包！');
                }

                if  ($redPacketInfo['type'] == Status::RED_PACKET_TYPE_EXCLUSIVE) {
                    // 不是自己的红包不能领取
                    if ($redPacketInfo['to_id'] != $user['id']) {
                        $data['state'] = 5;
                        return Functions::formatRestAPI(0, '', $data);
                    }
                }
            }

            if ($redPacketInfo['status'] != Status::RED_PACKET_WAIT) {
                if ($redPacketInfo['status'] == Status::RED_PACKET_DONE) {
                    $data['state'] = 3;   // 已被领取完
                    return Functions::formatRestAPI(0, '', $data);
                } else {
                    if (date('Y-m-d H:i:s') >= date('Y-m-d H:i:s',strtotime("+1 days",strtotime($redPacketInfo['create_time'])))) {
                        $data['state'] = 4;   // 红包已过期
                        return Functions::formatRestAPI(0, '', $data);
                    }
                }
            }

            $where['user_id'] = $redPacketInfo['user_id'];
            $where['red_packet_id'] = $redPacketInfo['id'];
            $where['receive_user_id'] = $user['id'];
            $where['status'] = Status::RED_PACKET_DONE;
            $isReceive = \api\modules\v1\models\redPacket\RedPacketLog::getOneByWhere($where,'id');
            if ($isReceive) {
                $data['state'] = 2;   // 已领取
                return Functions::formatRestAPI(0, '', $data);
            } else {
                $data['state'] = 1;   // 未领取
                return Functions::formatRestAPI(0, '', $data);
            }

        } catch (\yii\db\Exception $ee) {
            return Functions::formatRestAPI(1, '数据异常');
        } catch(Exception $e) {
            return Functions::formatRestAPI(1,$e->getMessage());
        }
    }


    // 新版发红包
    public function generateRedPacket($total, $num, $average) {
        // 创建一个长度为num-1的结果数组
        $result = [];
        // 初始化总金额
        $sum = (float) $total;

        // 遍历每一个人
        for ($i = 0; $i < $num-1; $i++) {
            // 从总金额中随机获取一定的金额
            $amount = mt_rand() / mt_getrandmax() * ($sum * $average / $num);
            // 将金额转换为两位小数
//            $amount = (float) number_format($amount, 2);
            $amount = $this->formatMoney($amount);

            // 如果金额为0，则重新随机获取一定的金额
            while ($amount == 0) {
                $amount = mt_rand() / mt_getrandmax() * ($sum * 2 / $num);
                $amount = $this->formatMoney($amount);
            }

            // 将金额存入结果数组
            $result[$i] = number_format($amount, 2, '.', '');
            // 总金额减去金额
            $sum -= $amount;
        }

        // 将总金额存入结果数组
        $result[$num-1] = number_format($sum, 2, '.', '');
        // 返回结果数组
        return $result;
    }

    private function sendOpen($params = [], $userId = 0) {
        $params['user_id'] = $userId;
//        // 发送红包
        $url = Yii::$app->params['OPEN_API'];
        $curl = new Curl();
        $curl->setPostParams($params);
        $res = $curl->post($url);
        return json_decode($res, true);
    }


}
